import DebugExt from "./DebugExt";

/** 多语言数据基础结构 */
interface BaseLangData {
    [lang: string]: string;
}
/** 简易的单层多语言数据结构 */
export interface SimpleLangData {
    [key: string]: BaseLangData;
}

/** 简易多语言数据对象，用于UI内专用多语言，便于UI移植 */
export default class UILangData {

    constructor(langList: string[], baseLang?: string) {
        this._baseLang = baseLang;
        this.uiLangList = langList;
    }

    // 备选语言
    private _baseLang: string = '';
    // 数据信息
    private _data: { [lang: string]: any } = {};

    // UI预期的多语言列表
    private _uiLangList: string[] = [];
    /**
     * 当前支持的多语言列表
     */
    get uiLangList(): string[] {
        const limitList = this._uiLangList;
        if (limitList && limitList.length > 0)
            return limitList;

        let list: string[] = [];
        for (const key in this._data) {
            if (key && key.length)
                list.push(key);
        }
        return list;
    }
    /**
     * 限制切换多语言UI的语言列表
     * 不设置的话，读取所有可用的语言列表
     * @param list 手动指定可切换的语言列表
     */
    set uiLangList(list: string[]) {
        if (list && list.length > 0) {
            this._uiLangList.splice(0);
            list.forEach(str => {
                if (str && str.length > 0)
                    this._uiLangList.push(str);
            });
        }
    }

    // UI是否支持指定语言
    private enableLang(lang: string): boolean {
        const list = this.uiLangList;
        if (list.length == 0)
            return false;
        return list.findIndex(str => str == lang) >= 0;
    }

    /**
     * 按照指定语言，设置多语言数据
     * @param lang 语言类型字符串
     * @param jsonObj 语言对应的json文本对象
     */
    public setLangData(lang: string, jsonObj: { [key: string]: any }) {
        if (!lang || lang.length == 0)
            return;
        this._data[lang] = jsonObj;
    }

    /**
     * 按照指定的key，设置多语言数据
     * @param key 多语言的key
     * @param langObj 当前key对应的文本多语言对象
     */
    public setkeyLangData(key: string, langObj: BaseLangData, logSwitch: boolean = true) {
        if (!key || key.length == 0 || !langObj)
            return;

        for (const lang in langObj) {
            if (!lang || lang.length == 0)
                continue;
            let langData = this._data[lang];
            if (!langData)
                langData = this._data[lang] = {};
            langData[key] = langObj[lang];
        }
        if (logSwitch) {
            DebugExt.group("【UILangData】 setkeyLangData");
            DebugExt.log("成功写入多语言数据, key:", key, " data:", langObj);
            DebugExt.table(this._data);
            DebugExt.groupEnd();
        }
    }

    /**
     * 简易格式的多语言数据解析
     * @param json SimpleLangData，数据源
     */
    public setJsonLangData(json: SimpleLangData) {
        if (!json) return;
        for (const key in json) {
            if (Object.prototype.hasOwnProperty.call(json, key)) {
                const data = json[key];
                this.setkeyLangData(key, data, false);
            }
        }
        DebugExt.group("【UILangData】setJsonLangData");
        DebugExt.log("成功写入多语言数据, json:", json);
        DebugExt.table(this._data);
        DebugExt.groupEnd();
    }

    /**
     * 获取指定key的转义后文本
     * @param key 键值
     */
    public getString(key: string, ...param: Array<string | number>): string {
        let content: string = this.getOriginalContent(key);
        // 查询替换参数
        if (param && param.length > 0 && content && content.length > 0) {
            for (let i = 0; i < param.length; i++) {
                const str: string = '' + param[i];
                const simple = "{&" + i + "}";
                // 无标识参数直接填到末尾
                if (content.search(simple) >= 0)
                    content = content.replace(simple, str);
                else
                    content += str;
            }
        }
        return content;
    }

    // 查找key对应的原始文本
    private getOriginalContent(key: string): string {
        const curlan = yy.curLanguage;
        if (!this._data || !key || key.length == 0) {
            DebugExt.debug('[MutiLang] 未配置多语言(', curlan, ')数据配置！key:', key);
            return key;
        }

        // 拆分查询路径
        const paths: string[] = key.split(".");
        // 查询function
        const search = (data: any, path: string[]): string => {
            // check input
            if (!data || !path.length) return "";
            // 遍历paths
            for (let i = 0; i < paths.length; i++) {
                if (!paths[i] || !paths[i].length) {
                    DebugExt.debug(`[MutiLang] 多语言键值路径异常，key:${key}`);
                    return "";
                }
                data = data[paths[i]];
                if (!data) return "";
            }
            return data || "";
        };

        // check current language
        if (this.enableLang(curlan)) {
            const langData = this._data[curlan];
            const str = search(langData, paths);
            if (str.length > 0)
                return str;
        }
        // check sub language
        if (!!this._baseLang && curlan != this._baseLang && this.enableLang(this._baseLang)) {
            const langData = this._data[this._baseLang];
            const str = search(langData, paths);
            if (str.length > 0)
                return str;
        }

        DebugExt.debug('[MutiLang] 未配置多语言(', curlan, ')数据配置！key:', key);
        return key;
    }

    /**
     * 获取指定key的转义后文本
     * @param key 键值
     * @param lang 指定语言
     */
    public getStringByLang(key: string, lang: string, ...param: Array<string | number>): string {
        let content: string = this.getOriginalContentByLang(key, lang);
        // 查询替换参数
        if (param && param.length > 0 && content && content.length > 0) {
            for (let i = 0; i < param.length; i++) {
                const str: string = '' + param[i];
                const simple = "{&" + i + "}";
                // 无标识参数直接填到末尾
                if (content.search(simple) >= 0)
                    content = content.replace(simple, str);
                else
                    content += str;
            }
        }
        return content;
    }

    // 查找指定语言的原始文本
    private getOriginalContentByLang(key: string, lang: string): string {
        if (!this._data || !key || key.length == 0) {
            DebugExt.debug('[MutiLang] 未配置多语言(', lang, ')数据配置！key:', key);
            return key;
        }
        // 拆分查询路径
        const paths: string[] = key.split(".");
        // 查询function
        const search = (data: any, path: string[]): string => {
            // check input
            if (!data || !path.length) return "";
            // 遍历paths
            for (let i = 0; i < paths.length; i++) {
                if (!paths[i] || !paths[i].length) {
                    DebugExt.debug(`[MutiLang] 多语言键值路径异常，key:${key}`);
                    return "";
                }
                data = data[paths[i]];
                if (!data) return "";
            }
            return data || "";
        };

        if (this.enableLang(lang)) {
            const langData = this._data[lang];
            const str = search(langData, paths);
            if (str.length > 0)
                return str;
        }

        DebugExt.debug('[MutiLang] 未配置多语言(', lang, ')数据配置！key:', key);
        return key;
    }

}
